"""
Redis工具类，用于存储和管理聊天消息
"""
import json
import redis
from datetime import datetime, timedelta
from django.conf import settings


class ChatRedisManager:
    """聊天消息Redis管理器"""
    
    def __init__(self):
        """初始化Redis连接"""
        self.redis_client = redis.Redis(
            host=settings.REDIS_CONFIG['host'],
            port=settings.REDIS_CONFIG['port'],
            password=settings.REDIS_CONFIG['password'],
            db=settings.REDIS_CONFIG['db'],
            decode_responses=True
        )
        self.expire_days = settings.CHAT_MESSAGE_EXPIRE_DAYS
    
    def _get_conversation_key(self, conversation_id):
        """获取会话消息的Redis键"""
        return f"chat:conversation:{conversation_id}:messages"
    
    def _get_user_conversations_key(self, user_id):
        """获取用户会话列表的Redis键"""
        return f"chat:user:{user_id}:conversations"
    
    def save_message(self, conversation_id, message_data):
        """
        保存消息到Redis
        
        Args:
            conversation_id: 会话ID
            message_data: 消息数据字典，包含：
                - id: 消息ID
                - content: 消息内容
                - sender_id: 发送者ID
                - sender_username: 发送者用户名
                - sender_nickname: 发送者昵称
                - sender_avatar: 发送者头像URL
                - created_at: 创建时间（ISO格式字符串）
                - message_type: 消息类型
                - is_read: 是否已读
        """
        key = self._get_conversation_key(conversation_id)
        
        # 添加时间戳用于排序
        timestamp = datetime.now().timestamp()
        
        # 将消息数据序列化为JSON
        message_json = json.dumps(message_data, ensure_ascii=False)
        
        # 使用ZADD添加到有序集合，以时间戳为分数
        self.redis_client.zadd(key, {message_json: timestamp})
        
        # 设置过期时间
        expire_seconds = self.expire_days * 24 * 60 * 60
        self.redis_client.expire(key, expire_seconds)
        
        return True
    
    def get_messages(self, conversation_id, limit=100, offset=0):
        """
        获取会话的消息列表
        
        Args:
            conversation_id: 会话ID
            limit: 返回消息数量限制
            offset: 偏移量
            
        Returns:
            消息列表，按时间正序排列
        """
        key = self._get_conversation_key(conversation_id)
        
        # 从有序集合中获取消息（按时间戳正序）
        start = offset
        end = offset + limit - 1
        messages_json = self.redis_client.zrange(key, start, end)
        
        # 反序列化消息
        messages = []
        for msg_json in messages_json:
            try:
                message = json.loads(msg_json)
                messages.append(message)
            except json.JSONDecodeError:
                continue
        
        return messages
    
    def get_latest_message(self, conversation_id):
        """
        获取会话的最新消息
        
        Args:
            conversation_id: 会话ID
            
        Returns:
            最新消息字典，如果没有消息则返回None
        """
        key = self._get_conversation_key(conversation_id)
        
        # 获取最后一条消息
        messages_json = self.redis_client.zrange(key, -1, -1)
        
        if not messages_json:
            return None
        
        try:
            return json.loads(messages_json[0])
        except (json.JSONDecodeError, IndexError):
            return None
    
    def get_message_count(self, conversation_id):
        """
        获取会话的消息总数
        
        Args:
            conversation_id: 会话ID
            
        Returns:
            消息总数
        """
        key = self._get_conversation_key(conversation_id)
        return self.redis_client.zcard(key)
    
    def delete_message(self, conversation_id, message_id):
        """
        删除指定消息
        
        Args:
            conversation_id: 会话ID
            message_id: 消息ID
            
        Returns:
            是否删除成功
        """
        key = self._get_conversation_key(conversation_id)
        
        # 获取所有消息
        messages_json = self.redis_client.zrange(key, 0, -1)
        
        # 查找并删除指定消息
        for msg_json in messages_json:
            try:
                message = json.loads(msg_json)
                if message.get('id') == message_id:
                    self.redis_client.zrem(key, msg_json)
                    return True
            except json.JSONDecodeError:
                continue
        
        return False
    
    def update_message_read_status(self, conversation_id, message_ids):
        """
        更新消息的已读状态
        
        Args:
            conversation_id: 会话ID
            message_ids: 消息ID列表
            
        Returns:
            更新的消息数量
        """
        key = self._get_conversation_key(conversation_id)
        
        # 获取所有消息
        messages_json = self.redis_client.zrange(key, 0, -1, withscores=True)
        
        updated_count = 0
        for msg_json, score in messages_json:
            try:
                message = json.loads(msg_json)
                if message.get('id') in message_ids:
                    # 更新已读状态
                    message['is_read'] = True
                    updated_json = json.dumps(message, ensure_ascii=False)
                    
                    # 删除旧消息，添加新消息
                    self.redis_client.zrem(key, msg_json)
                    self.redis_client.zadd(key, {updated_json: score})
                    updated_count += 1
            except json.JSONDecodeError:
                continue
        
        return updated_count
    
    def clear_conversation(self, conversation_id):
        """
        清空会话的所有消息
        
        Args:
            conversation_id: 会话ID
            
        Returns:
            是否清空成功
        """
        key = self._get_conversation_key(conversation_id)
        return self.redis_client.delete(key) > 0
    
    def save_conversation_info(self, user_id, conversation_id, other_user_data, last_message_time=None):
        """
        保存用户的会话信息到Redis
        
        Args:
            user_id: 用户ID
            conversation_id: 会话ID
            other_user_data: 对方用户信息字典
            last_message_time: 最后消息时间
        """
        key = self._get_user_conversations_key(user_id)
        
        conversation_data = {
            'conversation_id': conversation_id,
            'other_user': other_user_data,
            'last_message_time': last_message_time or datetime.now().isoformat()
        }
        
        conversation_json = json.dumps(conversation_data, ensure_ascii=False)
        
        # 使用时间戳作为分数
        timestamp = datetime.now().timestamp()
        self.redis_client.zadd(key, {conversation_json: timestamp})
        
        # 设置过期时间
        expire_seconds = self.expire_days * 24 * 60 * 60
        self.redis_client.expire(key, expire_seconds)
    
    def get_user_conversations(self, user_id):
        """
        获取用户的会话列表
        
        Args:
            user_id: 用户ID
            
        Returns:
            会话列表，按最后消息时间倒序排列
        """
        key = self._get_user_conversations_key(user_id)
        
        # 获取所有会话（按时间戳倒序）
        conversations_json = self.redis_client.zrevrange(key, 0, -1)
        
        conversations = []
        for conv_json in conversations_json:
            try:
                conversation = json.loads(conv_json)
                conversations.append(conversation)
            except json.JSONDecodeError:
                continue
        
        return conversations


# 创建全局实例
chat_redis = ChatRedisManager()
